package com.dzl.util;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.util.CellRangeAddressList;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * @Description: excel工具类
 * @author: liuguanjun
 * date 2021-10-15 13:45
 */
public class ExcelUtil {


    public static void main(String[] args) {
        try {
            File f= new File("e:" + File.separator + "test.xls") ;
            OutputStream out = new FileOutputStream(f);//导出本地
            //OutputStream out = response.getOutputStream();//输出客户端
            List<List<String>> data1 = new ArrayList<>();
            List<List<String>> data2 = new ArrayList<List<String>>();
            List<List<String>> data3 = new ArrayList<List<String>>();
            for (int i = 1; i < 5; i++) {
                List rowData = new ArrayList();
                rowData.add(String.valueOf(i));
                rowData.add("上海东霖柏鸿");
                data1.add(rowData);
            }
            for (int i = 1; i < 5; i++) {
                List rowData = new ArrayList();
                rowData.add(String.valueOf(i));
                rowData.add("深圳东霖柏鸿");
                data2.add(rowData);
            }
            for (int i = 1; i < 5; i++) {
                List rowData = new ArrayList();
                rowData.add(String.valueOf(i));
                rowData.add("广州东霖柏鸿");
                data3.add(rowData);
            }
            String[] headers1 = { "ID1", "用户名1" };
            String[] headers2 = { "ID2", "用户名2" };
            String[] headers3 = { "ID3", "用户名3" };
            ExcelUtil eeu = new ExcelUtil();//工具类写法在下面
            HSSFWorkbook workbook = new HSSFWorkbook();
            eeu.exportExcel(workbook, 0, "上海", headers1, data1, out);
            eeu.exportExcel(workbook, 1, "深圳", headers2, data2, out);
            eeu.exportExcel(workbook, 2, "广州", headers3, data3, out);
            //原理就是将所有的数据一起写入，然后再关闭输入流。
            workbook.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * @Title: exportExcel
     * @Description: 导出Excel的方法
     * @author: liuguanjun
     * date 2021-10-15 13:45
     * @param workbook
     * @param sheetNum (sheet的位置，0表示第一个表格中的第一个sheet)
     * @param sheetTitle （sheet的名称）
     * @param headers （表格的标题）
     * @param result （表格的数据）
     * @param out （输出流）
     */
    public static void exportExcel(HSSFWorkbook workbook, int sheetNum,
                            String sheetTitle, String[] headers, List<List<String>> result,
                            OutputStream out) throws Exception {
        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet();
        workbook.setSheetName(sheetNum, sheetTitle);
        // 设置表格默认列宽度为20个字节
        //sheet.setDefaultColumnWidth((short) 30);
        // 生成一个样式
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置这些样式
        style.setFillForegroundColor(HSSFColor.PALE_BLUE.index);

        style.setFillBackgroundColor(HSSFColor.WHITE.index);
        style.setFillForegroundColor(HSSFColor.LIGHT_ORANGE.index);

        // 生成一个字体
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.BLACK.index);
        font.setFontHeightInPoints((short) 10);
        //font.setBoldweight((short) 500);
        // 把字体应用到当前的样式
        style.setFont(font);
        // 指定当单元格内容显示不下时自动换行
        style.setWrapText(true);

        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        for (int i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell((short) i);
            cell.setCellStyle(style);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text.toString());
        }
        // 遍历集合数据，产生数据行
        if (result != null) {
            int index = 1;
            for (List<String> m : result) {
                row = sheet.createRow(index);
                int cellIndex = 0;
                for (String str : m) {
                    HSSFCell cell = row.createCell((short) cellIndex);
                    cell.setCellValue(str);
                    cellIndex++;
                }
                index++;
            }
            // 必须在单元格设值以后进行
            // 设置为根据内容自动调整列宽
            for (int k = 0; k < headers.length; k++) {
                sheet.autoSizeColumn(k);
            }
            // 处理中文不能自动调整列宽的问题
            setSizeColumn(sheet, headers.length);
        }
    }

    // 自适应宽度(中文支持)
    private static void setSizeColumn(HSSFSheet sheet, int size) {
        for (int columnNum = 0; columnNum < size; columnNum++) {
            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
            for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
                HSSFRow currentRow;
                //当前行未被使用过
                if (sheet.getRow(rowNum) == null) {
                    currentRow = sheet.createRow(rowNum);
                } else {
                    currentRow = sheet.getRow(rowNum);
                }

                if (currentRow.getCell(columnNum) != null) {
                    HSSFCell currentCell = currentRow.getCell(columnNum);
                    if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
                        int length = currentCell.getStringCellValue().getBytes().length;
                        if (columnWidth < length) {
                            columnWidth = length;
                        }
                    }
                }
            }
            sheet.setColumnWidth(columnNum, columnWidth * 256);
        }
    }



    /**
     * 43      *  excel导出，有码值的数据使用下拉框展示。解决下拉框最多255个字符的问题。
     * 44      *  原理为新建一个隐藏状态的sheet页，用来存储下拉框的值。
     * 45      * @param wb        　　 工作簿  HSSFWorkbook
     * 46      * @param col        　　当前列名
     * 47      * @param boxMap     　　码值集合
     * 48      * @param rows       　　正常sheet页数据，用来指定哪些行需要添加下拉框
     * 49      * @param i            　多个码值需要添加下拉，隐藏状态的sheet页名称不能重复，添加i值区分。
     * 50      * @param colToIndex    用来指定哪些列需要添加下拉框
     * 51      * @return  dataValidation
     * 52
     */
    public static HSSFDataValidation createBox1(HSSFWorkbook wb, String col, Map<String, String> boxMap, int rows, int i, int colToIndex) {
        HSSFDataValidation dataValidation = null;
        String cols = "";
        //查询码值集合,获取当前列的码值。
        if (null != boxMap.get(col)) {
            cols = boxMap.get(col);
        }
        //新建隐藏状态的sheet，用来存储码值。
        if (cols.length() > 0 && null != cols) {
            String str[] = cols.split(",");
            //创建sheet页
            HSSFSheet sheet = wb.createSheet("hidden" + i);
            //向创建的sheet页添加码值数据。
            for (int i1 = 0; i1 < str.length; i1++) {
                HSSFRow row = sheet.createRow(i1);
                HSSFCell cell = row.createCell((int) 0);
                cell.setCellValue(str[i1]);
            }
            //将码值sheet页做成excel公式
            Name namedCell = wb.createName();
            namedCell.setNameName("hidden" + i);
            namedCell.setRefersToFormula("hidden" + i + "!$A$1:$A$" + str.length);
            //确定要在哪些单元格生成下拉框
            DVConstraint dvConstraint = DVConstraint.createFormulaListConstraint("hidden" + i);
            CellRangeAddressList regions = new CellRangeAddressList(1, rows, colToIndex, colToIndex);
            dataValidation = new HSSFDataValidation(regions, dvConstraint);
            //隐藏码值sheet页
            int sheetNum = wb.getNumberOfSheets();
            for (int n = 1; n < sheetNum; n++) {
                wb.setSheetHidden(n, true);
            }
        }
        return dataValidation;
    }
}
